package com.leyou.item.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.vo.PageResult;
import com.leyou.item.dto.CategoryDto;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.Sku;
import com.leyou.item.entity.Spu;
import com.leyou.item.entity.SpuDetail;
import com.leyou.item.mapper.SkuMapper;
import com.leyou.item.mapper.SpuDetailMapper;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.common.utils.BeanHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static com.leyou.common.constants.MQConstants.Exchange.ITEM_EXCHANGE_NAME;
import static com.leyou.common.constants.MQConstants.RoutingKey.ITEM_DOWN_KEY;
import static com.leyou.common.constants.MQConstants.RoutingKey.ITEM_UP_KEY;

/**
 * @author syf
 * @version 1.0
 * @date 2019/08/03 17:41
 * @Description TODO:
 */
@Service
@Transactional
public class GoodsService {

    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SpuMapper spuMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private SpuDetailMapper spuDetailMapper;

    @Autowired
    private AmqpTemplate amqpTemplate;

    public PageResult<SpuDTO> SpuPageQuery(Integer page, Integer rows, String key, Boolean saleable) {
        Example example = new Example(Spu.class);

        Example.Criteria criteria = example.createCriteria();
        //封装查询条件
        if (StringUtils.isNotBlank(key)){
            criteria.andLike("name","%"+key+"%");
        }
        //封装上下架
        if (saleable!=null){
            criteria.andEqualTo("saleable",saleable);
        }

        //设置分页信息
        PageHelper.startPage(page,rows);
        //进行mybatis查询
        List<Spu> spus = spuMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(spus)){
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        //得到分页对象
        PageInfo<Spu> pageInfo=new PageInfo<>(spus);

        //吧spu转变成SpuDTO
        List<SpuDTO> spuDTOS = BeanHelper.copyWithCollection(pageInfo.getList(), SpuDTO.class);
        //对spuDTOS进行处理，给品牌名称和分类名称赋值
        handlerCategoryNameAndBrandName(spuDTOS);
        //封装分页结果集
        return new PageResult<>(pageInfo.getTotal(),pageInfo.getPages(),spuDTOS);
    }

    private void handlerCategoryNameAndBrandName(List<SpuDTO> spuDTOS) {
        spuDTOS.forEach(spuDTO -> {//遍历spuDTO，临时变量为spuDTO
            String categoryName = categoryService.findListByIds(spuDTO.getCategoryIds())//得到所有分类对象的集合
                    .stream()//吧分类集合变成流
                    .map(CategoryDto::getName)//在map中对每一个对象进行处理，得到商品分类的名称
                    .collect(Collectors.joining("/"));//收集所有分类名称，并以 / 连接
             spuDTO.setCategoryName(categoryName);

            String name = brandService.findBrandById(spuDTO.getBrandId()).getName();
            spuDTO.setBrandName(name);
        });
    }

    /**'
     * 新增商品信息
     * @param spuDTO
     * @return
     */
    public void saveGoods(SpuDTO spuDTO) {

        try {

            //保存spu
            //把spuDTO转为spu
            Spu spu = BeanHelper.copyProperties(spuDTO, Spu.class);
            spuMapper.insertSelective(spu);

            //保存spuDetailDTO
            SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
            SpuDetail spuDetail = BeanHelper.copyProperties(spuDetailDTO, SpuDetail.class);
            spuDetail.setSpuId(spu.getId());
            spuDetailMapper.insertSelective(spuDetail);

            //保存sku集合
            List<SkuDTO> skuDTOS = spuDTO.getSkus();
            List<Sku> skus = BeanHelper.copyWithCollection(skuDTOS, Sku.class);
            //遍历skus，给每一个sku中的spuId赋值
            skus.forEach(sku -> {
                sku.setSpuId(spu.getId());
                sku.setCreateTime(new Date());
                sku.setUpdateTime(new Date());
            });
            skuMapper.insertList(skus);

        }catch (Exception e){
            //新增操作失败
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
    }

    /**
     * 商品上下架
     * @param id
     * @param saleable
     */
    public void updateById(Long id, Boolean saleable) {
        try {

            //修改spu中的上下架
            Spu spu = new Spu();
            spu.setId(id);
            spu.setSaleable(saleable);
            spuMapper.updateByPrimaryKeySelective(spu);

            //封装要修改的数据
            Sku sku = new Sku();
            sku.setEnable(saleable);
            //封装修改的条件
            Example example = new Example(Sku.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("spuId",id);

            //修改sku中的字段，update tb_sku set enable=#{} where spu_id=#{}
            skuMapper.updateByExampleSelective(sku,example);

            //向队列发送消息
            //上架或下架
            String routinKey=saleable ? ITEM_UP_KEY : ITEM_DOWN_KEY;
            //交换机名称
            amqpTemplate.convertAndSend(ITEM_EXCHANGE_NAME,routinKey,id);
        }catch (Exception e){
            //更新失败
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
    }



    /**
     * 修改商品信息
     * 查询SpuDetail接口
     * @param id
     * @return
     */
    public SpuDetailDTO SpuDetailById(Long id) {

        SpuDetail spuDetail = spuDetailMapper.selectByPrimaryKey(id);
        if (spuDetail==null){
            //商品不存在
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return BeanHelper.copyProperties(spuDetail,SpuDetailDTO.class);
    }

    /**
     * 修改商品信息
     * 根据spuID查询sku
     * @param id
     * @return
     */
    public List<SkuDTO> skuBySpuId(Long id) {

        Sku record=new Sku();
        record.setSpuId(id);
        List<Sku> skuList = skuMapper.select(record);
        if (CollectionUtils.isEmpty(skuList)){
            //商品不存在
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }

        return BeanHelper.copyWithCollection(skuList,SkuDTO.class);

    }

    /**
     * 修改商品接口
     * @param spuDTO
     * @return
     */
    public void updateGoods(SpuDTO spuDTO) {

        try {
            //修改spu
            //把SpuDTO转为spu
            Spu spu = BeanHelper.copyProperties(spuDTO, Spu.class);
            //设置成下架
            spu.setSaleable(false);
            //更新操作
            spuMapper.updateByPrimaryKeySelective(spu);

            //修改spuDetail
            //获取spuDetail
            SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
            //转成spuDetail
            SpuDetail spuDetail = BeanHelper.copyProperties(spuDetailDTO, SpuDetail.class);
            //更新操作
            spuDetailMapper.updateByPrimaryKeySelective(spuDetail);

            //删除但钱spu下的所有sku
            Sku record = new Sku();
            record.setSpuId(spuDTO.getId());
            skuMapper.delete(record);
            //保存sku集合
            List<SkuDTO> skuDTOS = spuDTO.getSkus();
            List<Sku> skus = BeanHelper.copyWithCollection(skuDTOS, Sku.class);
            //遍历skus，给每一个sku中的spuId赋值
            skus.forEach(sku ->{
                sku.setSpuId(spu.getId());
                sku.setEnable(false);
                sku.setCreateTime(new Date());
                sku.setUpdateTime(new Date());
            } );
            skuMapper.insertList(skus);


        }catch (Exception e){
            //更新操作失败
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }


    }

    //根据spuId查询spu信息
    public SpuDTO findSpuIdBySpu(Long id) {
        //根据id查询sup对象
        Spu spu = spuMapper.selectByPrimaryKey(id);
        //把spu转成spuDTO
        SpuDTO spuDTO = BeanHelper.copyProperties(spu, SpuDTO.class);

        //调用方法获取spuDetailDTO
        SpuDetailDTO spuDetailDTO = SpuDetailById(spuDTO.getId());
        //把spuDetailDTO放入到spuDTO中
        spuDTO.setSpuDetail(spuDetailDTO);

        //调用方法获取skuDTO对象
        List<SkuDTO> skuDTOS = skuBySpuId(spuDTO.getId());
        //把skuDTO放入到spuDTO中
        spuDTO.setSkus(skuDTOS);
        return spuDTO;

    }

    //根据sku的id集合获取sku集合信息
    public List<SkuDTO> findSkuBuSkuIds(List ids) {
        List skus = skuMapper.selectByIdList(ids);
        if (CollectionUtils.isEmpty(skus)){
            //商品不存在
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return BeanHelper.copyWithCollection(skus,SkuDTO.class);
    }

    //减库存接口
    public void minusStock(Map<Long, Integer> cartMap) {
        try {
            //遍历map
            Set<Map.Entry<Long, Integer>> entries = cartMap.entrySet();
            for (Map.Entry<Long, Integer> entry : entries) {
                //得到skuId
                Long skuID = entry.getKey();
                //根据skuId查询出数据库中对应的sku
                Sku sku = skuMapper.selectByPrimaryKey(skuID);

                //封装根据id做修改的条件
                Sku record=new Sku();
                record.setId(skuID);
                record.setStock(sku.getStock()-entry.getValue());
                skuMapper.updateByPrimaryKeySelective(record);

            }

        }catch (Exception e){
            //库存不足
            throw new LyException(ExceptionEnum.STOCK_NOT_ENOUGH_ERROR);
        }

    }
}
